package gaml.yaml.ahchor;

import gaml.error.GamlException;
import gaml.java.ClassSerializerStore;
import gaml.java.NodeObjectBridge;
import gaml.yaml.AliasNode;
import gaml.yaml.YamlNode;

import java.util.HashMap;


/**
 * restore objects by linked
 * unique yaml anchors in deserializing nodes
 * @author shnireck
 *
 */
public class YamlAnchorCodeStore {
	final static String duplicateAnchorCode = "Duplicate anchor codes for different nodes [%s]";
	
	HashMap <String, YamlAnchor> anchors = new HashMap <String, YamlAnchor> ();

	/**
	 * realizing object for alias node
	 * deserializing referenced node if it's not
	 * deserialized already
	 * @param <T> type of deserializing object
	 * @param alias alias node to get deserializing object for
	 * @param clazz deserializing object class
	 * @return deserialized object for node, which alias referenced
	 * @throws GamlException could not realize object, on which node referes 
	 */
	public <T> T getObject (AliasNode alias, Class <T> clazz, ClassSerializerStore store) throws GamlException {
		if (null == alias.getAnchor ().getObject ()) {
			NodeObjectBridge <T> bridge = NodeObjectBridge.create (alias.getAnchor ().getNode (), clazz, store);
			alias.getAnchor ().setObject (bridge.getObject ());
			bridge.parseNode (this);
		}

		return (T) alias.getAnchor ().getObject ();
	}
	
	/**
	 * check if anchor with specified code exists
	 *  in store
	 * @param code anchor code
	 * @return true if anchor exists, false if not
	 */
	public boolean hasAnchor (String code) { return anchors.containsKey (code); }
	
	/**
	 * get anchor by code for
	 * not known yaml node
	 * @param code string code specified for anchor
	 * @return anchor by code
	 */
	public YamlAnchor getAnchor (String code) {
		if (! hasAnchor (code)) anchors.put (code, new YamlAnchor (code, null));
		return anchors.get (code);
	}
	
	/**
	 * anchor by it's code 
	 * @param code anchor's code
	 * @param node node, referenced by anchor
	 * @return anchor with specified code from store
	 */
	public YamlAnchor getAnchor (String code, YamlNode node) throws GamlException {
		if (hasAnchor (code)) anchors.get (code).setNode (node);
		else anchors.put (code, new YamlAnchor (code, node));
		
		return node.setAnchor (anchors.get (code)).getAnchor ();
	}
}